package com.jctrip.hotel.route.interceptor;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jctrip.hotel.domain.dao.HtRouteInfoDao;
import com.jctrip.hotel.domain.entity.HtRouteInfo;
import com.jctrip.hotel.route.common.ThreadLocalSession;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.nio.charset.StandardCharsets;

/**
 * 渠道接口3.0 拦截器
 */
@Slf4j
public class RouteOpenApiInterceptor implements HandlerInterceptor {

    @Autowired
    private HtRouteInfoDao htRouteInfoDao;

    @Override
    public boolean preHandle(@NonNull HttpServletRequest request,
                             @NonNull HttpServletResponse response,
                             @NonNull Object handler) {
        String routeId = request.getHeader("routeId");
        if (StringUtils.isBlank(routeId)) {
            throw new RuntimeException("routeId不能为空");
        }
        String timestamp = request.getHeader("timestamp");
        if (StringUtils.isBlank(timestamp)) {
            throw new RuntimeException("timestamp不能为空");
        }
        if (Math.abs(System.currentTimeMillis() - NumberUtils.toLong(timestamp)) > 600_000L) {
            throw new RuntimeException("timestamp非当前时间");
        }
        String nonce = request.getHeader("nonce");
        if (StringUtils.isBlank(nonce)) {
            throw new RuntimeException("nonce不能为空");
        }
        if (nonce.length() < 16) {
            throw new RuntimeException("nonce长度不能小于16");
        }
        String sign = request.getHeader("sign");
        HtRouteInfo htRouteInfo = getRouteInfo(routeId);
        if (htRouteInfo == null) {
            throw new RuntimeException("渠道配置不存在:" + routeId);
        }
        if (htRouteInfo.getRouteStatus() != 1) {
            throw new RuntimeException("渠道配置未生效:" + routeId);
        }
        String mySign = makeSign(routeId, htRouteInfo.getRouteSecret(), timestamp, nonce);
        if (!mySign.equals(sign)) {
            throw new RuntimeException("渠道签名校验失败:" + routeId);
        }
        ThreadLocalSession.RequestSession requestSession = ThreadLocalSession.RequestSession.builder()
                .routeInfo(htRouteInfo)
                .build();
        ThreadLocalSession.put(requestSession);
        return true;
    }

    /**
     * 生成用于校验的签名
     */
    private String makeSign(String routeId, String routeSecret, String timestamp, String nonce) {
        String preSign = String.format("routeId=%s&routeSecret=%s&timestamp=%s&nonce=%s",
                routeId, routeSecret, timestamp, nonce);
        return DigestUtils.sha256Hex(preSign.getBytes(StandardCharsets.UTF_8));
    }

    @Override
    public void afterCompletion(@NonNull HttpServletRequest request,
                                @NonNull HttpServletResponse response,
                                @NonNull Object handler,
                                @Nullable Exception e) {
        ThreadLocalSession.clear();
    }

    private HtRouteInfo getRouteInfo(String routeId) {
        LambdaQueryWrapper<HtRouteInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(HtRouteInfo::getRouteId, routeId);
        return htRouteInfoDao.selectOne(queryWrapper);
    }
}
